home *** CD-ROM | disk | FTP | other *** search
/ Network CD 2 / Network CD - Volume 2.iso / programs / internet / envoy / talk_svc120a.lha / tk.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-17  |  23.3 KB  |  696 lines

  1. /*************************************************************************
  2. Talk Service written by Jeffrey A. Litz
  3.  
  4. litz@cs.uwp.edu  -or-  Jeff_Litz@EDTNG.Kenosha.WI.US
  5.  
  6. Copyright ©1994 JL Productions.
  7. *************************************************************************/
  8.  
  9. #include <exec/types.h>
  10. #include <exec/memory.h>
  11. #include <exec/ports.h>
  12. #include <exec/semaphores.h>
  13. #include <exec/io.h>
  14. #include <devices/printer.h>
  15. #include <devices/timer.h>
  16. #include <devices/parallel.h>
  17. #include <devices/serial.h>
  18.  
  19. #include <intuition/intuition.h>
  20. #include <intuition/classes.h>
  21. #include <intuition/classusr.h>
  22. #include <intuition/imageclass.h>
  23. #include <intuition/gadgetclass.h>
  24. #include <libraries/gadtools.h>
  25. #include <graphics/displayinfo.h>
  26. #include <graphics/gfxbase.h>
  27. #include <clib/intuition_protos.h>
  28. #include <clib/gadtools_protos.h>
  29. #include <clib/graphics_protos.h>
  30.  
  31. #include <envoy/nipc.h>
  32. #include <envoy/services.h>
  33.  
  34. #include <pragmas/exec_pragmas.h>
  35. #include <pragmas/nipc_pragmas.h>
  36. #include <pragmas/dos_pragmas.h>
  37. #include <pragmas/utility_pragmas.h>
  38.  
  39. #include <utility/tagitem.h>
  40. #include <clib/dos_protos.h>
  41. #include <clib/exec_protos.h>
  42. #include <clib/nipc_protos.h>
  43. #include <clib/alib_protos.h>
  44. #include <clib/utility_protos.h>
  45.  
  46. #include <string.h>
  47.  
  48. #include "tkbase.h"
  49.  
  50. #define GD_Gadget00                            0
  51. #define GD_Gadget10                            1
  52.  
  53. #define TKCMD_TALK 1
  54. #define TKCMD_ABORT 2
  55. #define TKCMD_DATA 3
  56.  
  57. extern STRPTR       TALKUser;
  58. extern STRPTR       TALKPassword;
  59. extern STRPTR       TALKEntityName;
  60. extern ULONG        TALKSignalMask;
  61. extern ULONG        TALKError;
  62. extern struct Task *TALKSMProc;
  63.  
  64. extern __far TALKServer(void);
  65.  
  66. struct Library *GadToolsBase,*IntuitionBase;
  67.  
  68.  
  69. /*************************************************************************/
  70. /*************************************************************************/
  71. /* Generic Requester */
  72.  
  73. struct Screen        *Scr = NULL;
  74. APTR                  VisualInfo = NULL;
  75. struct Window        *Project0Wnd = NULL;
  76. struct Gadget        *Project0GList = NULL;
  77. struct Gadget        *Project0Gadgets[2];
  78. UWORD                 Project0Left = 0;
  79. UWORD                 Project0Top = 0;
  80. UWORD                 Project0Width = 278;
  81. UWORD                 Project0Height = 55;
  82. UBYTE                *Project0Wdt = "** TALK REQUESTED **";
  83.  
  84. struct TextAttr topaz8 = {
  85.     ( STRPTR )"topaz.font", 8, 0x00, 0x00 };
  86.  
  87. struct IntuiText  Project0IText[] = {
  88.     1, 0, JAM1,40, 7, &topaz8, NULL, NULL };
  89.  
  90. /* VERY Quick kludge for long names */
  91. struct IntuiText  Project0IText1[] = {
  92.     1, 0, JAM1,40, 7, &topaz8, NULL, NULL };
  93. struct IntuiText  Project0IText2[] = {
  94.     1, 0, JAM1,40, 7, &topaz8, NULL, NULL };
  95.  
  96.  
  97. long SetupScreen( void )
  98. {
  99.     if ( NOT( Scr = LockPubScreen( NULL )))
  100.         return( 1L );
  101.  
  102.     if ( NOT( VisualInfo = GetVisualInfo( Scr, TAG_DONE )))
  103.         return( 2L );
  104.  
  105.     return( NULL );
  106. }
  107.  
  108. void CloseDownScreen( void )
  109. {
  110.     if ( VisualInfo ) {
  111.         FreeVisualInfo( VisualInfo );
  112.         VisualInfo = NULL;
  113.     }
  114.  
  115.     if ( Scr        ) {
  116.         UnlockPubScreen( NULL, Scr );
  117.         Scr = NULL;
  118.     }
  119. }
  120.  
  121.  
  122. void Project0Render(void)
  123. {
  124.     /* VERY Quick kludge to work with long names */
  125.  
  126.     UWORD  offy;
  127.     WORD   xpos;
  128.     WORD   two;
  129.  
  130.     UBYTE str1[36];
  131.     UBYTE str2[36];
  132.     
  133.     offy = Project0Wnd->BorderTop;
  134.  
  135.     Project0IText1->IText=&str1[0];
  136.     Project0IText2->IText=&str2[0];
  137.     
  138.     if(strlen(Project0IText->IText) > 32)
  139.     {
  140.         strncpy(Project0IText1->IText,Project0IText->IText,32);
  141.         Project0IText1->IText[32]=0;
  142.         strncpy(Project0IText2->IText,&Project0IText->IText[32],32);
  143.         two=3;
  144.     } else
  145.     {
  146.         strcpy(Project0IText1->IText,Project0IText->IText);
  147.         two=7;
  148.     }
  149.  
  150.  
  151.     if((xpos=Project0Width-IntuiTextLength(Project0IText1)) < 0)
  152.       xpos=0;
  153.     Project0IText1->LeftEdge=xpos>>1;
  154.     
  155.     PrintIText( Project0Wnd->RPort, Project0IText1, 0, offy+two );
  156.     two += 9;
  157.  
  158.     if(two==12)
  159.     {
  160.         if((xpos=Project0Width-IntuiTextLength(Project0IText2)) < 0)
  161.             xpos=0;
  162.         Project0IText2->LeftEdge=xpos>>1;
  163.     
  164.         PrintIText( Project0Wnd->RPort, Project0IText2, 0, offy+two );
  165.     }
  166. }
  167.  
  168. long OpenProject0Window(char *hostname)
  169. {
  170.     struct NewGadget     ng;
  171.     struct Gadget       *g;
  172.     UWORD               offx, offy;
  173.  
  174.     offx = Scr->WBorLeft;
  175.     offy = Scr->WBorTop + Scr->RastPort.TxHeight + 1;
  176.  
  177.     if ( NOT( g = CreateContext( &Project0GList )))
  178.         return( 1L );
  179.  
  180.     ng.ng_LeftEdge        =    offx + 10;
  181.     ng.ng_TopEdge         =    offy + 35;
  182.     ng.ng_Width           =    76;
  183.     ng.ng_Height          =    16;
  184.     ng.ng_GadgetText      =    (UBYTE *)"TALK";
  185.     ng.ng_TextAttr        =    &topaz8;
  186.     ng.ng_GadgetID        =    GD_Gadget00;
  187.     ng.ng_Flags           =    PLACETEXT_IN;
  188.     ng.ng_VisualInfo      =    VisualInfo;
  189.  
  190.     g = CreateGadget( BUTTON_KIND, g, &ng, TAG_DONE );
  191.  
  192.     Project0Gadgets[ 0 ] = g;
  193.  
  194.     ng.ng_LeftEdge        =    offx + 176;
  195.     ng.ng_Width           =    83;
  196.     ng.ng_GadgetText      =    (UBYTE *)"IGNORE";
  197.     ng.ng_GadgetID        =    GD_Gadget10;
  198.  
  199.     g = CreateGadget( BUTTON_KIND, g, &ng, TAG_DONE );
  200.  
  201.     Project0Gadgets[ 1 ] = g;
  202.  
  203.     if ( NOT g )
  204.         return( 2L );
  205.  
  206.     if ( NOT( Project0Wnd = OpenWindowTags( NULL,
  207.                     WA_Left,          Project0Left,
  208.                     WA_Top,           Project0Top,
  209.                     WA_Width,         Project0Width,
  210.                     WA_Height,        Project0Height + offy,
  211.                     WA_IDCMP,         BUTTONIDCMP|IDCMP_MENUPICK|IDCMP_CLOSEWINDOW|IDCMP_REFRESHWINDOW,
  212.                     WA_Flags,         WFLG_DRAGBAR|WFLG_DEPTHGADGET|WFLG_SMART_REFRESH|WFLG_ACTIVATE,
  213.                     WA_Gadgets,       Project0GList,
  214.                     WA_Title,         Project0Wdt,
  215.                     WA_ScreenTitle,   "Talk Service",
  216.                     WA_PubScreen,     Scr,
  217.                         TAG_DONE )))
  218.         return( 4L );
  219.  
  220.     GT_RefreshWindow( Project0Wnd, NULL );
  221.  
  222.     Project0IText->IText=hostname;
  223.     
  224.     Project0Render();
  225.  
  226.     return( NULL );
  227. }
  228.  
  229. void CloseProject0Window( void )
  230. {
  231.     if ( Project0Wnd        ) {
  232.         CloseWindow( Project0Wnd );
  233.         Project0Wnd = NULL;
  234.     }
  235.  
  236.     if ( Project0GList      ) {
  237.         FreeGadgets( Project0GList );
  238.         Project0GList = NULL;
  239.     }
  240. }
  241.  
  242. /*************************************************************************/
  243. /*************************************************************************/
  244.  
  245.  
  246.  
  247. /**************************************************************************
  248. O_Request() - Open a request on this machine
  249.  
  250.     When ever this service is "found", it attempts to bring workbench
  251.     forward, open a requester and wait for a response.  It will idle
  252.     timeout in 15 seconds.
  253.  
  254.     INPUTS: hosename, entity, and entity signal
  255.     OUTPUT: 0 means start a talk, 1 means "ignore" me
  256. **************************************************************************/
  257. UBYTE O_Request(char *hostname,void *entity,ULONG ent_sigbit)
  258. {
  259.    struct IntuiMessage *mess;
  260.    struct Transaction *w_trans;
  261.    UBYTE r_value=2;
  262.    struct MsgPort *TimerMP;
  263.    struct timerequest *TimerIO;
  264.    ULONG signal;
  265.    
  266.    if(TimerMP=CreateMsgPort())
  267.    {
  268.       if(TimerIO=(struct timerequest *)CreateExtIO(TimerMP,sizeof(struct timerequest)))
  269.       {
  270.          if(!(OpenDevice(TIMERNAME,UNIT_VBLANK,(struct IORequest *)TimerIO,0)))
  271.          {
  272.             if(IntuitionBase=OpenLibrary("intuition.library",37L))
  273.             { 
  274.                if(GadToolsBase=OpenLibrary("gadtools.library",37L))
  275.                {
  276.                   if(WBenchToFront())
  277.                   {
  278.                      if(!SetupScreen())
  279.                      {
  280.                         if(!OpenProject0Window(hostname))
  281.                         {
  282.                            TimerIO->tr_node.io_Command=TR_ADDREQUEST;
  283.                            TimerIO->tr_time.tv_secs=15;
  284.                            TimerIO->tr_time.tv_micro=0;
  285.                            SendIO((struct IORequest *)TimerIO);
  286.                                    
  287.                            while(TRUE)
  288.                            {
  289.                               if(mess=(struct IntuiMessage *)GetMsg(Project0Wnd->UserPort))
  290.                               {
  291.                                  if(mess->Class == IDCMP_GADGETUP) 
  292.                                  {
  293.                                     r_value=((struct Gadget *)mess->IAddress)->GadgetID;
  294.                                  }
  295.                                  ReplyMsg((struct Message *)mess);
  296.                               } else if(w_trans=GetTransaction(entity))
  297.                               {
  298.                                  w_trans->trans_Error=1;
  299.                                  ReplyTransaction(w_trans);
  300.                               } else
  301.                               {
  302.                                  signal=Wait((1<<Project0Wnd->UserPort->mp_SigBit) | (1<<ent_sigbit) | (1L << TimerMP->mp_SigBit));
  303.                                  if(signal & (1L << TimerMP->mp_SigBit))
  304.                                  {
  305.                                     if(GetMsg(TimerMP))
  306.                                     {
  307.                                        r_value=1;
  308.                                     }
  309.                                  }
  310.                               }
  311.                               if(r_value != 2)
  312.                               {
  313.                                  break;
  314.                               }
  315.                            }
  316.  
  317.                            if(!(CheckIO((struct IORequest *)TimerIO)))
  318.                            {
  319.                               AbortIO((struct IORequest *)TimerIO);
  320.                            }
  321.                            WaitIO((struct IORequest *)TimerIO);
  322.  
  323.                            CloseProject0Window();
  324.                         }
  325.                         CloseDownScreen();
  326.                      }
  327.                   } else
  328.                   {
  329.                      r_value=1;
  330.                   }
  331.                   CloseLibrary(GadToolsBase);
  332.                }
  333.                CloseLibrary(IntuitionBase);
  334.             }
  335.             CloseDevice((struct IORequest *)TimerIO);
  336.          }
  337.          DeleteExtIO((struct IORequest *)TimerIO);
  338.       }
  339.       DeleteMsgPort(TimerMP);
  340.    }
  341.    return(r_value);
  342. }
  343.  
  344.  
  345.  
  346.  
  347. /**************************************************************************
  348. StartService() - Starts the service.
  349.  
  350.     Services Manager calls this function to attempt to start the service.
  351.  
  352.     INPUTS: TagList passed in by Services Manager
  353.     OUTPUT: Error Code - Non Zero Means Error
  354. **************************************************************************/
  355. ULONG __saveds ASM StartService(REG(a0) struct TagItem *st_list)
  356. {
  357.     struct TagItem cptags[3];
  358.     struct Process *lpdproc;
  359.     BOOL   status = FALSE;
  360.     UBYTE  sigbit;
  361.     struct TagItem *tag;
  362.     
  363.     
  364.     /* Check to see if service is already open */
  365.     
  366.     if(!TALKBase->TALK_Entity)
  367.     {
  368.         /* Nope - Try starting it up */
  369.         
  370.         if(sigbit = AllocSignal(-1L))
  371.         {
  372.             TALKSMProc = FindTask(0L);
  373.             TALKSignalMask = (1L<<sigbit);
  374.  
  375.             cptags[0].ti_Tag  = NP_Entry;
  376.             cptags[0].ti_Data = (ULONG) TALKServer;
  377.             cptags[1].ti_Tag  = NP_Name;
  378.             cptags[1].ti_Data = (ULONG) "TK Daemon";
  379.             cptags[2].ti_Tag  = TAG_DONE;
  380.             cptags[2].ti_Data = NULL;
  381.         
  382.             /* Process tags passed in by services manager */
  383.             
  384.             if(tag=FindTagItem(SSVC_UserName,st_list))
  385.             {
  386.                 TALKUser = (STRPTR) tag->ti_Data;
  387.             }
  388.  
  389.             if(tag=FindTagItem(SSVC_Password,st_list))
  390.             {
  391.                 TALKPassword = (STRPTR) tag->ti_Data;
  392.             }
  393.             
  394.             if(tag=FindTagItem(SSVC_EntityName,st_list))
  395.             {
  396.                 TALKEntityName = (STRPTR) tag->ti_Data;
  397.             }
  398.             
  399.             /* Try to start the process */
  400.             
  401.             if(lpdproc = CreateNewProc((struct TagItem *)cptags))
  402.             {
  403.                 Wait(1L<<sigbit);
  404.                 status = TRUE;
  405.             }
  406.             FreeSignal(sigbit);
  407.         }
  408.     }
  409.     else
  410.     {
  411.         /* Service process already running... simply pass back its entity name */
  412.         
  413.         if(tag=FindTagItem(SSVC_EntityName,st_list))
  414.         {
  415.             strcpy((STRPTR)tag->ti_Data,"TK_Service");
  416.             TALKError = 0;
  417.         } else
  418.         {
  419.             TALKError = -1;
  420.         }
  421.     }
  422.     return(TALKError);
  423. }
  424.  
  425.  
  426.  
  427.  
  428. VOID ASM GetServiceAttrsA(REG(a0) struct TagItem *tagList)
  429. {
  430.     struct TagItem *ti;
  431.  
  432.     /* Return our service name - REQUIRED!!! */
  433.     if(ti=FindTagItem( SVCAttrs_Name, tagList))
  434.     {
  435.         strcpy((STRPTR)ti->ti_Data,"Talk_Service");
  436.     }
  437. }
  438.  
  439.  
  440.  
  441.  
  442. VOID ASM Server(REG(a0) STRPTR userName,REG(a1) STRPTR password,REG(a2) STRPTR EntityName)
  443. {
  444.    struct Library *SvcBase;
  445.    ULONG signals;
  446.    ULONG waitmask;
  447.    ULONG StartupError;
  448.    ULONG ent_sigbit;
  449.    struct MsgPort *port,*replyport;
  450.    UBYTE host_name[256],userinput[256],work_space[512],sys_name[256];
  451.    UBYTE done;
  452.    BPTR output_w=0,input_w=0;
  453.    int howmany;
  454.    UBYTE logins=0;
  455.    struct StandardPacket *packet;
  456.    void *entity,*t_entity,*s_entity;
  457.    struct Transaction *trans,*a_trans;
  458.    struct TagItem cetags[4],cbtags[2],ttags[3];
  459.  
  460.    geta4();
  461.      
  462.    /* Initialize TagItems for entity and transaction creations */
  463.  
  464.    ent_sigbit = 0;
  465.  
  466.    cetags[0].ti_Tag=ENT_Name;
  467.    cetags[0].ti_Data=(ULONG) "TK_Service";
  468.    cetags[1].ti_Tag=ENT_Public;
  469.    cetags[1].ti_Data=TRUE;
  470.    cetags[2].ti_Tag=ENT_AllocSignal;
  471.    cetags[2].ti_Data=(ULONG) &ent_sigbit;
  472.    cetags[3].ti_Tag=TAG_END;
  473.    cetags[3].ti_Data=0;
  474.  
  475.    cbtags[0].ti_Tag=ENT_AllocSignal;
  476.    cbtags[0].ti_Data=NULL;
  477.    cbtags[1].ti_Tag=TAG_END;
  478.    cbtags[1].ti_Data=0;
  479.  
  480.    ttags[0].ti_Tag=TRN_AllocReqBuffer;
  481.    ttags[0].ti_Data=516;
  482.    ttags[1].ti_Tag=TRN_AllocRespBuffer;
  483.    ttags[1].ti_Data=4;
  484.    ttags[2].ti_Tag=TAG_END;
  485.    ttags[2].ti_Data=0;
  486.  
  487.    StartupError = -1;
  488.    
  489.    if (SvcBase = OpenLibrary("talk.service", 0L))
  490.    {
  491.       /* Create an entity which everyone can find */
  492.       if (entity = CreateEntityA((struct TagItem *) cetags))
  493.       {
  494.          /* Find out exactly who WE are */
  495.          GetHostName(entity,host_name,255);
  496.  
  497.          /* Create an entity for RECEIVING data from outside */
  498.          if(t_entity=CreateEntityA((struct TagItem *) cbtags))
  499.          {
  500.             /* Create a transaction for sending data */
  501.             if(a_trans=AllocTransactionA((struct TagItem *) ttags))
  502.             {
  503.                /* Create a msgport for use in keyboard packet input */
  504.                if(replyport=(struct MsgPort *) CreateMsgPort())
  505.                {
  506.                   /* Setup our service entity and name */
  507.                   TALKBase->TALK_Entity = entity;
  508.                   strcpy(EntityName,"TK_Service");
  509.  
  510.                   TALKError = StartupError = 0;
  511.                   
  512.                   /* Signal StartService() that everything appears to be OK and we are ready */
  513.                   Signal(TALKSMProc, TALKSignalMask);
  514.  
  515.                   /* Setup waitmask for keyboard and transaction inputs */
  516.                   waitmask = (1<<replyport->mp_SigBit) | (1<<ent_sigbit);
  517.  
  518.                   done=0;
  519.                                 
  520.                   while(TRUE)
  521.                   {
  522.                      signals = Wait(waitmask);
  523.                      
  524.                      /* Did we receive a transaction */
  525.                      if(signals & (1<<ent_sigbit))
  526.                      {
  527.                         /* Get transaction */
  528.                         if(trans = GetTransaction(entity))
  529.                         {
  530.                            if((trans->trans_Command == TKCMD_DATA) && (logins))
  531.                            {
  532.                               /* Data transaction - send to output window */
  533.                               Write(output_w,(UBYTE *)((UBYTE *)trans->trans_RequestData+4),trans->trans_ReqDataActual-4);
  534.                            }
  535.                            if(trans->trans_Command == TKCMD_TALK)
  536.                            {
  537.                               /* Talk request - check to see if we are "busy" */
  538.                               if(logins)
  539.                               {
  540.                                  /* YEP - already talking */
  541.                                  trans->trans_Error=1;
  542.                               } else
  543.                               {
  544.                                  logins=1;
  545.                                  
  546.                                  /* Find out what system wishes to talk by reading the transaction buffer */
  547.                                  strcpy(sys_name,(UBYTE *)((UBYTE *)trans->trans_RequestData+4));
  548.                                  
  549.                                  /* Open a requester */
  550.                                  if(!O_Request(sys_name,entity,ent_sigbit))
  551.                                  {
  552.                                     trans->trans_Error=3;
  553.                                     done=3;
  554.                                     
  555.                                     /* Locate the entity to talk back to */
  556.                                     if(s_entity=FindEntity(sys_name,"talk_back",t_entity,NULL))
  557.                                     {
  558.                                        /* Open windows and alloc & setup packet for waitforchar input */
  559.                                        if(output_w=(BPTR)Open("CON:1/1/640/150/Output Window Service",MODE_NEWFILE))
  560.                                        {
  561.                                           if(input_w=(BPTR)Open("CON:1/150/640/50/Input Window Service/CLOSE",MODE_NEWFILE))
  562.                                           {
  563.                                              if(packet=(struct StandardPacket *)AllocMem((long)sizeof(struct StandardPacket),MEMF_PUBLIC|MEMF_CLEAR))
  564.                                              {
  565.                                                 done=0;
  566.                                                 trans->trans_Error=0;
  567.                                                 port=(struct MsgPort *) (((struct FileHandle *)((ULONG)input_w<<2))->fh_Type);
  568.                                                 packet->sp_Msg.mn_Node.ln_Name=(char *)&(packet->sp_Pkt);
  569.                                                 packet->sp_Pkt.dp_Link=&(packet->sp_Msg);
  570.                                                 packet->sp_Pkt.dp_Port=replyport;
  571.                                                 packet->sp_Pkt.dp_Type=ACTION_WAIT_CHAR;
  572.                                                 packet->sp_Pkt.dp_Arg1=34000;
  573.                                                 SendPkt(&packet->sp_Pkt,port,replyport);
  574.                                              }
  575.                                           }
  576.                                        }
  577.                                     }
  578.                                  } else
  579.                                  {
  580.                                     trans->trans_Error=2;
  581.                                     done=1;
  582.                                  }
  583.                               }
  584.                            }
  585.  
  586.                            /* cancel talk */
  587.                            if(trans->trans_Command == TKCMD_ABORT)
  588.                            {
  589.                               trans->trans_Error=0;
  590.                               done=1;
  591.                            }
  592.                            ReplyTransaction(trans);
  593.                         }
  594.                      }
  595.  
  596.                      /* Is it a keyboard input? */
  597.                      if(signals & (1<<replyport->mp_SigBit))
  598.                      {
  599.                         /* check to make sure we are actually connected to someone */
  600.                         if(logins)
  601.                         {
  602.                            /* check to make sure we actually received something */
  603.                            if(GetMsg(replyport))
  604.                            {
  605.                               if(packet->sp_Pkt.dp_Res1)
  606.                               {
  607.                                  if(!(howmany=Read(input_w,userinput,255)))
  608.                                  {
  609.                                     /* Close gadget - exit talk */
  610.                                     done=2;
  611.                                  } else
  612.                                  {
  613.                                     /* send output to our window as well as to other side */
  614.                                     userinput[howmany]=0;
  615.                                     sprintf(work_space,"(%s) %s\n",host_name,userinput);
  616.  
  617.                                     Write(output_w,work_space,strlen(work_space));
  618.                                              
  619.                                     a_trans->trans_Command=TKCMD_DATA;
  620.                                     *(ULONG *)(a_trans->trans_RequestData)=*(ULONG *)(a_trans->trans_ResponseData);
  621.                                     strcpy(((UBYTE *)a_trans->trans_RequestData+4),work_space);
  622.                                     a_trans->trans_ReqDataActual=strlen(work_space)+4;
  623.                                     a_trans->trans_Timeout=10;
  624.                                     DoTransaction(s_entity,t_entity,a_trans);
  625.                                  }
  626.                               }
  627.                               /* send a packet for another waitforchar input */
  628.                               packet->sp_Pkt.dp_Port=replyport;
  629.                               packet->sp_Pkt.dp_Type=ACTION_WAIT_CHAR;
  630.                               packet->sp_Pkt.dp_Arg1=34000;
  631.                               SendPkt(&packet->sp_Pkt,port,replyport);
  632.                            }
  633.                         }
  634.                      }
  635.                      if(done)
  636.                      {
  637.                         break;
  638.                      }
  639.                   }
  640.                   if(done == 2)
  641.                   {
  642.                      /* If we are initating the close - attempt to signal other side */
  643.                      howmany=4;
  644.                      while(howmany--)
  645.                      {
  646.                         a_trans->trans_ReqDataActual=4;
  647.                         a_trans->trans_Command=TKCMD_ABORT;
  648.                         a_trans->trans_Timeout=10;
  649.                         DoTransaction(s_entity,t_entity,a_trans);
  650.                         if(a_trans->trans_Error==0)
  651.                         {
  652.                                 break;
  653.                         }
  654.                      }
  655.                   }
  656.                   
  657.                   /* Attempt to clean up any stray transactions */
  658.                   while(trans = GetTransaction(entity))
  659.                   {
  660.                      trans->trans_Error=2;
  661.                      ReplyTransaction(trans);
  662.                   }                     
  663.  
  664.                   /* General clean up - close everything down and dealloc */
  665.                   
  666.                   TALKBase->TALK_Entity = NULL;
  667.                   
  668.                   while((ULONG *)GetMsg(replyport) != (ULONG *)&packet->sp_Msg);
  669.                   if(output_w)
  670.                      Close(output_w);
  671.                   if(input_w)
  672.                      Close(input_w);
  673.                   if(s_entity)
  674.                      LoseEntity(s_entity);
  675.                   if(packet)
  676.                      FreeMem(packet,(long)sizeof(struct StandardPacket));
  677.                  DeleteMsgPort(replyport);
  678.                }
  679.                a_trans->trans_ReqDataLength=516;
  680.                FreeTransaction(a_trans);
  681.             }
  682.             DeleteEntity(t_entity);
  683.          }
  684.          DeleteEntity(entity);
  685.       }
  686.       if(StartupError) 
  687.       {
  688.          /* Oooppsss - there was a startup problem - signal StartService() */
  689.          TALKError = StartupError;
  690.          Signal(TALKSMProc, TALKSignalMask);
  691.       }
  692.       Forbid();        
  693.       CloseLibrary(SvcBase);
  694.    }
  695. }
  696.